package com.cls.business.controller;

import com.cls.business.entity.*;
import com.cls.business.service.*;
import com.cls.business.vo.DeclareTopicCount;
import com.cls.business.vo.DeclareTopicVO;
import com.cls.business.vo.TopicReviewInfoVO;
import com.cls.common.annotation.ControllerEndpoint;
import com.cls.common.controller.BaseController;
import com.cls.common.entity.MyConstant;
import com.cls.common.entity.QueryRequest;
import com.cls.common.entity.ResponseVO;
import com.cls.common.enums.DictEnum;
import com.cls.common.utils.FileUtil;
import com.cls.common.utils.MyUtil;
import com.cls.common.utils.ReportUtil;
import com.cls.system.entity.Configure;
import com.cls.system.entity.Expert;
import com.cls.system.entity.SysDict;
import com.cls.system.entity.User;
import com.cls.system.service.IConfigureService;
import com.cls.system.service.IExpertService;
import com.cls.system.service.ISysDictService;
import com.cls.system.service.IUserService;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.text.Collator;
import java.util.*;

/**
 * 评审管理 Controller
 *
 * @author weimaomao
 * @date 2020-11-10 11:09:57
 */
@Slf4j
@Validated
@Controller
@RequiredArgsConstructor
public class ReviewController extends BaseController {

    private final ITopicService topicService;

    private final IEntrustTopicService entrustTopicService;

    private final ISysDictService sysDictService;

    private final IExpertService expertService;

    private final IReviewService reviewService;

    private final IReviewDetailService reviewDetailService;

    private final ITopicSubjectService topicSubjectService;

    private final IUserService userService;

    private final ITopicPlanService topicPlanService;

    private final IExpertGroupService expertGroupService;

    private final IConfigureService configureService;

    /**
     * 评审列表页面
     *
     * @param model
     * @return
     */
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/review/{type}")
    public String reviewIndex(Model model, @PathVariable("type") String topicClassifyCode) {
        List<SysDict> subjectType = sysDictService.findByParentCode(DictEnum.SUBJECT_TYPE.getCode());
        model.addAttribute("topicClassifyCode", topicClassifyCode);
        model.addAttribute("subjectType", subjectType);
        List<SysDict> statusTypes = sysDictService.findByParentCode(DictEnum.TOPIC_PLAN_STATUS.getCode());
        model.addAttribute("statusTypes", statusTypes);
        if (DictEnum.ENTRUST.getCode().equals(topicClassifyCode)) {
            List<SysDict> planNos = sysDictService.findByParentCode(DictEnum.PLAN_NO.getCode());
            model.addAttribute("planNos", planNos);
            return MyUtil.view("business/review/listEntrust");
        }
        return MyUtil.view("business/review/listAnnual");
    }

    /**
     * 评审专家分配页面
     *
     * @param topicId
     * @param model
     * @return
     */
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/review/{topicId}/assign/{topicClassifyCode}")
    public String assignExpertIndex(@PathVariable("topicId") Long topicId, @PathVariable("topicClassifyCode") String topicClassifyCode, Model model) {
        model.addAttribute("topicId", topicId);
        model.addAttribute("topicClassifyCode", topicClassifyCode);
        model.addAttribute("operation", "showButton");
        return MyUtil.view("business/review/assign");
    }

    /**
     * 评审专家分配页面
     *
     * @param topicId
     * @param model
     * @return
     */
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/review/{topicId}/showExpert/{topicClassifyCode}")
    public String showExpertIndex(@PathVariable("topicId") Long topicId, @PathVariable("topicClassifyCode") String topicClassifyCode, Model model) {
        model.addAttribute("topicId", topicId);
        model.addAttribute("topicClassifyCode", topicClassifyCode);
        model.addAttribute("operation", "hiddenButton");
        return MyUtil.view("business/review/assign");
    }

    /**
     * 评审学科分类页面
     *
     * @param topicId
     * @param model
     * @return
     */
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/review/{topicId}/modifySubject/{topicClassifyCode}")
    public String modifySubjectIndex(@PathVariable("topicId") Long topicId, @PathVariable("topicClassifyCode") String topicClassifyCode, Model model) {
        Long planId = -1L;
        if (DictEnum.ANNUAL.getCode().equals(topicClassifyCode)) {
            Topic topic = topicService.getById(topicId);
            if (topic != null) {
                planId = topic.getPlanId();
            }
        } else {
            EntrustTopic topic = entrustTopicService.getById(topicId);
            if (topic != null) {
                planId = topic.getPlanId();
            } else {
                Topic topicNew = topicService.getById(topicId);
                if (topicNew != null) {
                    planId = topicNew.getPlanId();
                }
            }
        }
        model.addAttribute("topicClassifyCode", topicClassifyCode);
        model.addAttribute("topicId", topicId);
        model.addAttribute("planId", planId);
        return MyUtil.view("business/review/modifySubject");
    }

    /**
     * 分配专家评审课题列表详情
     *
     * @param expertGroupId
     * @param model
     * @return
     */
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/review/expertDetails/{expertGroupId}")
    public String expertDetailsIndex(@PathVariable Long expertGroupId, Model model) {
        model.addAttribute("expertGroupId", expertGroupId);
        return MyUtil.view("business/review/expertDetail");
    }

    /**
     * 增加学科页面
     *
     * @param topicId
     * @param model
     * @return
     */
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/review/{planId}/{topicId}/addSubject")
    public String addSubjectIndex(@PathVariable("planId") Long planId, @PathVariable("topicId") Long topicId, Model model) {
        TopicPlan topicPlan = topicPlanService.getById(planId);
        if (topicPlan == null) {
            throw new IllegalArgumentException("参数异常！");
        }
        String topicName = "";
        if (topicPlan != null) {
            if (DictEnum.ANNUAL.getCode().equals(topicPlan.getTopicClassifyCode())) {
                Topic topic = topicService.getById(topicId);
                if (topic != null) {
                    topicName = topic.getTopicName();
                }
            } else {
                EntrustTopic topic = entrustTopicService.getById(topicId);
                if (topic != null) {
                    topicName = topic.getTopicName();
                }
            }
        }
        TopicSubjectDetail param = new TopicSubjectDetail();
        param.setTopicId(topicId);
        param.setPlanId(planId);

        model.addAttribute("planId", planId);
        model.addAttribute("topicId", topicId);
        model.addAttribute("topicName", topicName);
        //查询学科类型
        List<SysDict> subjectTypes = sysDictService.findByParentCode(DictEnum.SUBJECT_TYPE.getCode());
        model.addAttribute("subjectTypes", subjectTypes);
        return MyUtil.view("business/review/subjectAdd");
    }


    /**
     * 手动专家分配选择页面
     *
     * @param expertGroupId
     * @param model
     * @return
     */
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/review/expertGroup/{expertGroupId}")
    public String modifyExpertIndex(@PathVariable Long expertGroupId, Model model) {
        model.addAttribute("expertGroupId", expertGroupId);
        List<SysDict> subjectTypes = sysDictService.findByParentCode(DictEnum.SUBJECT_TYPE.getCode());
        model.addAttribute("subjectTypes", subjectTypes);
        //行政职务
        List<SysDict> districts = sysDictService.findByParentCode(DictEnum.DISTRICT.getCode());
        model.addAttribute("districts", districts);
        //职称
        List<SysDict> features = sysDictService.findByParentCode(DictEnum.FEATURE.getCode());
        model.addAttribute("features", features);
        return MyUtil.view("business/review/expert");
    }

    /**
     * 课题指南列表数据
     *
     * @param request
     * @param topic
     * @return
     */
    @GetMapping("review/{topicClassifyCode}/list")
    @ResponseBody
    @RequiresPermissions("review:list")
    public ResponseVO reviewList(QueryRequest request, Topic topic, @PathVariable("topicClassifyCode") String topicClassifyCode) {
        if (StringUtils.isEmpty(topicClassifyCode)) {
            ResponseVO.failure("参数异常！");
        }
        topic.setTopicClassifyCode(topicClassifyCode);
        if (topicClassifyCode.equals(DictEnum.ENTRUST.getCode())) {
            EntrustTopic param = new EntrustTopic();
            String stage = topic.getYear() + '-' + topic.getPlanNo();
            param.setStage(stage);
            param.setTopicName(topic.getTopicName());
            if (!StringUtils.isEmpty(topic.getStatusTypeCode())) {
                param.setStatusTypeCode(topic.getStatusTypeCode());
            }
            return ResponseVO.success(entrustTopicService.findEntrustTopics(request, param));
        } else {

            return ResponseVO.success(topicService.findReviewTopics(request, topic));
        }
    }


    @GetMapping("review/getList/{reviewId}")
    @ResponseBody
    public ResponseVO getList(@PathVariable Long reviewId) {

        Review review = reviewService.getAllList(reviewId);
        if (review == null) {
            ResponseVO vo = new ResponseVO();
            vo.setData(review);
            vo.setMessage("数据为空");
            vo.setCode(HttpStatus.OK.value());
            return vo;
        }
        return ResponseVO.success(review);
    }

    @ControllerEndpoint(operation = "修改", exceptionMessage = "修改失败")
    @PostMapping("review/updateList")
    @ResponseBody
    public ResponseVO updateList(@RequestBody Review review) {
        this.reviewService.updateList(review);
        return ResponseVO.success("修改完成");
    }

    /**
     * 指定课题下评审专家组数据
     *
     * @param request
     * @param topicId
     * @return
     */
    @GetMapping("review/{topicId}/experts")
    @ResponseBody
    @RequiresPermissions("review:assignExpert")
    public ResponseVO reviewList(QueryRequest request, @PathVariable Long topicId) {

        ExpertGroup param = new ExpertGroup();
        param.setTopicId(topicId);
        PageInfo<ExpertGroup> groups = expertGroupService.findExpertGroups(request, param);
        return ResponseVO.success(groups);
    }


    @ControllerEndpoint(operation = "课题分类", exceptionMessage = "课题分类失败")
    @PostMapping("reviews/{planId}/{topicId}/classify")
    @ResponseBody
    @RequiresPermissions("review:assignExpert")
    public ResponseVO classifyTopic(@PathVariable("planId") Long planId, @PathVariable("topicId") Long topicId,
                                    @RequestBody List<TopicSubjectDetail> details) {
        if (topicId == null || details == null) {
            throw new IllegalArgumentException("参数错误");
        }

        TopicPlan plan = topicPlanService.getById(planId);
        if (plan == null) {
            return ResponseVO.failure("期次不存在！");
        }

        // 核对每组专家个数
        Configure configure = configureService.getById(plan.getConfigureId());
        if (configure == null) {
            return ResponseVO.failure("请正确配置专家组人数！");
        }
        int num = configure.getExpertNum();
        if (details.size() > num) {
            return ResponseVO.failure("学科分类不能超出专家人数！");
        }


        if (!DictEnum.PLAN_CHECK.getCode().equals(plan.getStatusCode()) &&
                !DictEnum.PLAN_ASSIGN.getCode().equals(plan.getStatusCode())) {
            return ResponseVO.success("期次状态不正确！");
        }
        if (DictEnum.ANNUAL.getCode().equals(plan.getTopicClassifyCode())) {
            Topic topic = topicService.getById(topicId);
            if (topic == null) {
                return ResponseVO.success("选题信息不存在！");
            }
            topicService.classifyTopic(planId, topicId, details);
        } else {
            EntrustTopic entrustTopic = entrustTopicService.getById(topicId);
            if (entrustTopic == null) {
                return ResponseVO.success("选题信息不存在！");
            }
            topicService.classifyEntrustTopic(planId, topicId, details);
        }

        return ResponseVO.success("操作成功！");
    }

    /**
     * 手动调整专家
     *
     * @param expertGroupId
     * @param expertId
     * @return
     */
    @ControllerEndpoint(operation = "分配专家", exceptionMessage = "分配专家失败")
    @PostMapping("reviews/expertGroup/{expertGroupId}/commit/{expertId}")
    @ResponseBody
//    @RequiresPermissions("review:assignExpert")
    public ResponseVO assignExpertForDeclareTopic(@PathVariable Long expertGroupId, @PathVariable Long expertId) {
        if (expertGroupId == null || expertId == null) {
            throw new IllegalArgumentException("参数异常");
        }
        ExpertGroup expertGroup = expertGroupService.getById(expertGroupId);
        if (expertGroup == null) {
            return ResponseVO.failure("数据不存在！");
        }

        ExpertGroup param = new ExpertGroup();
        param.setTopicId(expertGroup.getTopicId());
        param.setGroupNo(expertGroup.getGroupNo());
        List<ExpertGroup> groups = expertGroupService.findExpertGroups(param);
        for (ExpertGroup one : groups) {
            if (expertId.equals(one.getExpertId())) {
                return ResponseVO.failure("该组中已存在该专家！");
            }
        }
        // 核对修改的专家是否已经存在这组中

        expertGroupService.modifyExpertGroup(expertGroup, expertId);
        return ResponseVO.success("修改成功！");
    }

    @ControllerEndpoint(operation = "确认专家", exceptionMessage = "确认专家失败")
    @PostMapping("reviews/{topicId}/experts/{topicClassifyCode}/confirm")
    @ResponseBody
//    @RequiresPermissions("review:assignExpert")
    public ResponseVO confirmExpertForDeclareTopic(@PathVariable("topicId") Long topicId, @PathVariable("topicClassifyCode") String topicClassifyCode, @RequestBody List<Expert> experts) {
        if (experts == null) {
            return ResponseVO.failure("参数错误");
        }

        // 课题状态判断
        ITopic topic;
        if (DictEnum.ANNUAL.getCode().equals(topicClassifyCode)) {
            topic = topicService.getById(topicId);
        } else {
            topic = entrustTopicService.getById(topicId);
            if(topic==null){
                topic = topicService.getById(topicId);
            }

        }

        if (topic == null) {
            return ResponseVO.failure("参数错误");
        }
        if (DictEnum.PLAN_EXPERT.getCode().equals(topic.getStatusTypeCode())) {
            return ResponseVO.success("专家确认已完成！");
        }
        long planId = topic.getPlanId();
        TopicPlan plan = topicPlanService.getById(planId);
        if (plan == null) {
            return ResponseVO.failure("参数错误");
        }

        // 计划状态判断
        if (!DictEnum.PLAN_SUBJECT.getCode().equals(plan.getStatusCode())) {
            return ResponseVO.failure("计划状态不正确！");
        }

        // 专家是否分配完成(通过期次Id + 选题Id)进行查询
        ExpertGroup param = new ExpertGroup();
        param.setTopicId(topicId);
        param.setPlanId(planId);
        List<ExpertGroup> groups = expertGroupService.findExpertGroups(param);
        boolean isAllExistExpert = true;
        for (ExpertGroup one : groups) {
            if (one.getExpertId() == null) {
                isAllExistExpert = false;
                break;
            }
        }
        if (!isAllExistExpert) {
            return ResponseVO.failure("存在未分配专家的申请课题！");
        }

        List<Expert> userExperts = new ArrayList();
        for (Expert one : experts) {
            Expert beforeExpert = expertService.getById(one.getExpertId());
            if (beforeExpert == null) {
                return ResponseVO.failure(one.getName() + "：专家不存在！");
            }
            if (beforeExpert.getUserId() == null) {
                userExperts.add(beforeExpert);
            }
        }
        userService.createExpertUsers(userExperts, topic);
        return ResponseVO.success("操作成功！");
    }

    @GetMapping("review/expertDetails/{expertGroupId}/list")
    @ResponseBody
    @RequiresPermissions("review:assignExpert")
    public ResponseVO reviewsByExpertId(QueryRequest request, @PathVariable Long expertGroupId) {
        ExpertGroup expertGroup = expertGroupService.getById(expertGroupId);
        if (expertGroup == null) {
            throw new IllegalArgumentException("参数错误!");
        }
        PageInfo<DeclareTopic> reviews = reviewService.findDeclareTopicsByPlanIDAndExpertId(request, expertGroup.getPlanId(), expertGroup.getExpertId());
        return ResponseVO.success(reviews);
    }

    @GetMapping("review/expert/list")
    @ResponseBody
//    @RequiresPermissions("declareTopic:list")
    public ResponseVO declareTopicList(QueryRequest request, DeclareTopic declareTopic) {
        User user = getCurrentUser();
        if (user == null) {
            throw new IllegalArgumentException("获取用户失败！");
        }
        Expert expert = expertService.findByUserId(user.getUserId());
        if (expert == null) {
            ResponseVO.failure("专家不存在！");
        }
        Map<String, Object> params = new HashMap();
        params.put("topicId", declareTopic.getTopicId());
        params.put("statusTypeCode", declareTopic.getStatusTypeCode());
        params.put("subjectTypeCode", declareTopic.getSubjectTypeCode());
        params.put("name", declareTopic.getName());
        params.put("expertId", expert.getExpertId());
        List statusCodes = new ArrayList();
        statusCodes.add(DictEnum.PLAN_EXPERT.getCode());
        statusCodes.add(DictEnum.PLAN_REVIEW.getCode());
        statusCodes.add(DictEnum.PLAN_ITEM.getCode());
        statusCodes.add(DictEnum.PLAN_CONCLUDE_FINISH.getCode());
        params.put("statusCodes", statusCodes);
        PageInfo<DeclareTopic> pageInfo = reviewService.selectDeclareTopicView(request, params);
        return ResponseVO.success(pageInfo);
    }

    @PostMapping("review/{reviewId}/commit")
    @ResponseBody
//    @RequiresPermissions("declareTopic:list")
    public ResponseVO declareTopicList(@PathVariable("reviewId") Long reviewId) {
        User user = getCurrentUser();
        if (user == null) {
            throw new IllegalArgumentException("获取用户失败！");
        }

        Review beforeReview = reviewService.getById(reviewId);
        if (beforeReview == null) {
            throw new IllegalArgumentException("获取评审记录失败！");
        }

        if (beforeReview.getIsSubmit()) {
            return ResponseVO.failure("已提交评审！");
        }
        List<ReviewDetail> details = reviewDetailService.findReviewDetailsByReviewId(reviewId);
        if (details == null || details.size() < 1) {
            return ResponseVO.failure("还没有评审记录存在！");
        }


        Review param = new Review();
        param.setDeclareId(beforeReview.getDeclareId());
        param.setPlanId(beforeReview.getPlanId());
        List<Review> reviews = reviewService.findReviews(param);

        // 最后一个专家的评分提交时，计算总分，设置申报课题为已评审状态
        boolean isAllSubmit = true;
        double totalScore = 0.0;
        for (Review one : reviews) {
            long curReviewId = one.getReviewId();
            if (!one.getIsSubmit() && curReviewId != reviewId) {
                isAllSubmit = false;
            }
            if (one.getScore() != null) {
                totalScore += one.getScore();
            }
        }
        beforeReview.setIsSubmit(true);
        if (isAllSubmit) {
            DeclareTopic declareTopic = new DeclareTopic();
            declareTopic.setDeclareId(beforeReview.getDeclareId());
            declareTopic.setStatusTypeCode(DictEnum.CHECK_PASSED_REVIEW.getCode());
            declareTopic.setScore(totalScore);
            DeclarePlan declarePlan = new DeclarePlan();
            declarePlan.setPlanScore(totalScore);
            declarePlan.setDeclareId(beforeReview.getDeclareId());
            declarePlan.setPlanId(beforeReview.getPlanId());
            reviewService.submitReview(beforeReview, declareTopic, declarePlan);
        } else {
            reviewService.submitReview(beforeReview, null, null);
        }

        return ResponseVO.success("提交成功");
    }

    @GetMapping("review/getScoreLogById/{reviewId}")
    @ResponseBody
    public ResponseVO getSoureLogById(QueryRequest request, @PathVariable("reviewId") Long reviewId) {

        PageInfo<ReviewDetail> pageInfo = reviewService.getSoureLogById(request, reviewId);
        return ResponseVO.success(pageInfo);
    }

    @GetMapping("review/getById/{reviewId}")
    @ResponseBody
    public ResponseVO getById(@PathVariable("reviewId") Long reviewId) {

        Review byId = reviewService.getById(reviewId);
        return ResponseVO.success(byId);
    }


    @ControllerEndpoint(operation = "导出选题申报情况表", exceptionMessage = "导出选题申报情况表失败")
    @GetMapping("review/{topicClassifyCode}/topicReviewInfo")
    @ResponseBody
    public void topicReviewInfo(Topic topic, @PathVariable("topicClassifyCode") String topicClassifyCode, HttpServletResponse response) {
        if (StringUtils.isEmpty(topicClassifyCode)) {
            throw new RuntimeException("参数异常！");
        }
        topic.setTopicClassifyCode(topicClassifyCode);
        Set<Long> topicIds = new HashSet();
        Map<Long, ITopic> topicNames = new HashMap();
        Map<String, TopicReviewInfoVO> topicReviewInfos = new TreeMap(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                String[] index1 = o1.split("-");
                String[] index2 = o2.split("-");
                if (index1 == null || index2 == null) {
                    return 0;
                }
                if (index1[0].compareTo(index2[0]) == 0) {
                    if (index1.length > 1 && index2.length > 1) {
                        return Integer.parseInt(index1[1]) - Integer.parseInt(index2[1]);
                    } else {
                        return 0;
                    }
                } else {
                    return o1.compareTo(o2);
                }

            }
        });
        String stage;
        if (topicClassifyCode.equals(DictEnum.ENTRUST.getCode())) {
            EntrustTopic param = new EntrustTopic();
            stage = topic.getYear() + '-' + topic.getPlanNo();
            param.setStage(stage);
            param.setTopicName(topic.getTopicName());
            List<EntrustTopic> entrustTopics = entrustTopicService.findEntrustTopics(param);
            for (EntrustTopic one : entrustTopics) {
                topicIds.add(one.getTopicId());
                topicNames.putIfAbsent(one.getTopicId(), one);
            }
        } else {
            stage = topic.getYear();
            List<Topic> topics = topicService.findReviewTopics(topic);
            for (Topic one : topics) {
                topicIds.add(one.getTopicId());
                topicNames.putIfAbsent(one.getTopicId(), one);
            }
        }
        TopicPlan plan = topicPlanService.selectByPeriod(stage);
        // 判断期次的状态
        String status = plan.getStatusCode();
        if (DictEnum.PLAN_CREATE.getCode().equals(status) || DictEnum.PLAN_CHECK.getCode().equals(status)) {
            throw new RuntimeException("请先结束学科分类！");
        }

        List<TopicSubject> subjects = topicSubjectService.findByTopicIds(topicIds);
        for (TopicSubject one : subjects) {
            ITopic iTopic = topicNames.get(one.getTopicId());
            if (iTopic != null) {
                TopicReviewInfoVO reviewInfo = topicReviewInfos.get(iTopic.getTopicCode());
                if (reviewInfo == null) {
                    reviewInfo = new TopicReviewInfoVO();
                    reviewInfo.setTopicName(iTopic.getTopicName());
                    reviewInfo.setTopicCode(iTopic.getTopicCode());
                    reviewInfo.setNum(one.getNum());
                    reviewInfo.setAdviseExpert(one.getSubjectTypeName() + " " + one.getSubjectNum());
                } else {
                    reviewInfo.setNum(reviewInfo.getNum() + one.getNum());
                    reviewInfo.setAdviseExpert(reviewInfo.getAdviseExpert() + " " + one.getSubjectTypeName() + " " + one.getSubjectNum());
                }
                topicReviewInfos.put(iTopic.getTopicCode(), reviewInfo);
            }
        }
        try {
            DeclareTopicCount aa = new DeclareTopicCount();
            aa.setTopicReviewInfos(topicReviewInfos);
            ReportUtil.generateFileByTemplate("topicReviewInfo.ftl", "test.doc", aa);
            FileUtil.download("test.doc", "test.doc", true, response);
        } catch (Exception e) {
            throw new RuntimeException("下载失败！");
        }
    }

    @ControllerEndpoint(operation = "导出专家评审名单", exceptionMessage = "导出专家评审名单失败")
    @GetMapping("review/{topicClassifyCode}/exportReviewExpertName")
    @ResponseBody
    public void exportReviewExpertName(Topic topic, @PathVariable("topicClassifyCode") String topicClassifyCode, HttpServletResponse response) {
        if (StringUtils.isEmpty(topicClassifyCode)) {
            throw new RuntimeException("参数异常！");
        }
        topic.setTopicClassifyCode(topicClassifyCode);
        Set<Long> topicIds = new HashSet();
        Map<Long, String> topicNames = new HashMap();
        String stage;
        if (topicClassifyCode.equals(DictEnum.ENTRUST.getCode())) {
            EntrustTopic param = new EntrustTopic();
            stage = topic.getYear() + '-' + topic.getPlanNo();
            param.setStage(stage);
            param.setTopicName(topic.getTopicName());
            List<EntrustTopic> entrustTopics = entrustTopicService.findEntrustTopics(param);
            for (EntrustTopic one : entrustTopics) {
                topicIds.add(one.getTopicId());
                topicNames.putIfAbsent(one.getTopicId(), one.getTopicName());
            }
        } else {
            stage = topic.getYear();
            List<Topic> topics = topicService.findReviewTopics(topic);
            for (Topic one : topics) {
                topicIds.add(one.getTopicId());
                topicNames.putIfAbsent(one.getTopicId(), one.getTopicName());
            }
        }
        if (topicIds.size() < 1) {
            throw new RuntimeException("未找到选题！");
        }
        List<ExpertGroup> expertGroups = expertGroupService.findByTopicIds(topicIds);
        if (expertGroups == null || expertGroups.size() < 1) {
            throw new RuntimeException("未找到专家组！");
        }
        Set<Long> expertIds = new HashSet();
        for (ExpertGroup one : expertGroups) {
            expertIds.add(one.getExpertId());
        }
        List<Expert> experts = expertService.findByIds(expertIds);
        TopicPlan plan = topicPlanService.selectByPeriod(stage);
        // 判断期次的状态
        String status = plan.getStatusCode();
        if (DictEnum.PLAN_CREATE.getCode().equals(status) || DictEnum.PLAN_CHECK.getCode().equals(status) || DictEnum.PLAN_SUBJECT.getCode().equals(status)) {
            throw new RuntimeException("请先结束专家分配！");
        }
        try {
            DeclareTopicCount declareTopicCount = new DeclareTopicCount();
            Collections.sort(experts, new Comparator<Expert>() {
                Collator cmp = Collator.getInstance(java.util.Locale.CHINA);

                @Override
                public int compare(Expert o1, Expert o2) {
                    return cmp.compare(o1.getName(), o2.getName());
                }
            });
            declareTopicCount.setExperts(experts);
            declareTopicCount.setNum(experts.size() + "");
            declareTopicCount.setYear(plan.getPeriod());
            ReportUtil.generateFileByTemplate("ExpertList.ftl", "expert.doc", declareTopicCount);
            FileUtil.download("expert.doc", "expert.doc", true, response);
        } catch (Exception e) {
            throw new RuntimeException("下载失败！");
        }
    }

}
